package com.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.Set;

public class MyNioServer {
	
	public static Selector selector;
	protected CharsetDecoder decoder; 
	
	public static int BLOCK_SIZE = 1024;
	
	private ByteBuffer byteBuffer;
	
	public MyNioServer(){
		selector = getSelector();
		Charset charset = Charset.forName("GB2312");   
        decoder = charset.newDecoder();  
	}
	
	private Selector getSelector(){
		try{
			ServerSocketChannel channel = ServerSocketChannel.open();
			Selector selector = Selector.open();
			channel.configureBlocking(false);
			channel.socket().bind(new InetSocketAddress("localhost",10084));
			channel.register(selector, SelectionKey.OP_ACCEPT);
			return selector;
		}catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public void busiHandler(SelectionKey key){
		try{
			byteBuffer = ByteBuffer.allocate(MyNioServer.BLOCK_SIZE);
		}catch (Exception e) {
			e.printStackTrace();
		}
		if(key.isAcceptable()){
			try{
				ServerSocketChannel schannel = (ServerSocketChannel)key.channel();
				SocketChannel channel = schannel.accept();
				channel.configureBlocking(false);
				channel.register(selector, SelectionKey.OP_READ);
			}catch (Exception e) {
				e.printStackTrace();
			}
		}else if(key.isReadable()){
			try{
				StringBuffer sBuffer = new StringBuffer();
				SocketChannel channel = (SocketChannel)key.channel();
				int size = 0;
				do{
					byteBuffer.clear();
					size = channel.read(byteBuffer);
					if(size == -1){
						channel.close();
						key.cancel();
					}
					byteBuffer.flip();
					CharBuffer charBuffer = decoder.decode(byteBuffer); 
					sBuffer.append(charBuffer.toString());
				}while(size > 0);
				System.out.println(sBuffer.toString());
				channel.register(selector, SelectionKey.OP_WRITE);
			}catch (Exception e) {
				e.printStackTrace();
			}
		}else if(key.isWritable()){
			try{
				SocketChannel channel = (SocketChannel) key.channel();
				ByteBuffer buffer = ByteBuffer.allocate(BLOCK_SIZE);
				buffer.put("Hello client".getBytes());
				buffer.flip();
				channel.write(buffer);
				channel.register(selector, key.interestOps()&~SelectionKey.OP_WRITE);
				//key.interestOps(SelectionKey.OP_READ);
				channel.close();
				
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args){
		try{
			MyNioServer myServer = new MyNioServer();
			System.out.println("Server start...");
			while(true){
				selector.select();
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> keyIts = keys.iterator();
				while(keyIts.hasNext()){
					SelectionKey key = (SelectionKey)keyIts.next();
					keyIts.remove();
					myServer.busiHandler(key);
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}
